﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;

namespace Test.Expressions
{
	

	/// <summary>
	/// Base subquery expression that has a SELECT clause and columns.
	/// </summary>
	public class SubqueryExpression : DbExpression
	{
		bool isDistinct;
		Expression from;
		Expression where;
		Expression take;
		Expression skip;
		
		public SubqueryExpression(
			Type type,
			IEnumerable<ColumnExpression> columns,
			Expression from,
			IEnumerable<Expression> appended = null,
			Expression where = null,
			Expression take = null,
			Expression skip = null,
			bool isDistinct = false
			) : this(DbExpressionType.Subquery, type: type,
			columns: columns, from: from, where: where, appended: appended, take: take, skip: skip, isDistinct: isDistinct){
			
		}
		public SubqueryExpression(DbExpressionType nodeType,
			Type type,
			IEnumerable<ColumnExpression> columns,
			Expression from,
			IEnumerable<Expression> appended = null,
			Expression where = null,
			Expression take = null,
			Expression skip = null,
			bool isDistinct = false)
			: base(nodeType: nodeType, type: type) {
			this.Columns = columns;
			this.from = from;
			this.where = where;
			this.Appended = appended == null? new List<Expression>() : new List<Expression>(appended);
			this.isDistinct = isDistinct;
			this.skip = skip;
			this.take = take;
		}


		public IEnumerable<ColumnExpression> Columns { get; internal set; }
		public Expression From {
			get { return this.from; }
		}
		public List<Expression> Appended { get; internal set; }
		public Expression Where {
			get { return this.where; }
			internal set { this.where = value; }
		}
		public IEnumerable<OrderExpression> OrderBy { get; private set; }
		public IEnumerable<Expression> GroupBy { get; private set; }

		public bool IsDistinct {
			get { return this.isDistinct; }
		}
		public Expression Skip {
			get { return this.skip; }
		}
		public Expression Take {
			get { return this.take; }
		}
	}

	public class AggregateSubqueryExpression : SubqueryExpression
	{
		public AggregateSubqueryExpression(DbExpressionType nodeType,
			Type returnType,
			IEnumerable<ColumnExpression> columns,
			Expression from,			
			MethodInfo method,  Expression where = null) 
			:base(nodeType: nodeType, type: returnType, columns: columns, from: from,  where: where, take: null, 
			skip: null, isDistinct: false) {
			/*lambda.ReturnType Count would have Boolean, so caller must provide return Type*/
				this.MethodCall = method;
		}				
		public MethodInfo MethodCall { get; private set; }		
	}


}
